package net.kucoe.grin.context;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import net.kucoe.grin.Validator;
import net.kucoe.grin.internal.interaction.exception.ParameterRelatedException;
import net.kucoe.grin.internal.interaction.exception.UnexpectedInteractionException;

/**
 * Describes wired {@link Validator} method.
 * 
 * @author Vitaliy Basyuk
 */
public class ContextValidator {
    
    private final Method method;
    private final Object invocationObject;
    
    /**
     * Constructs ContextValidator.
     * 
     * @param method
     * @param invocationObject
     */
    public ContextValidator(final Method method, final Object invocationObject) {
        this.method = method;
        this.invocationObject = invocationObject;
    }
    
    /**
     * Returns the method Method.
     * 
     * @return the method Method.
     */
    public Method getMethod() {
        return method;
    }
    
    /**
     * Invokes {@link Validator} method.
     * 
     * @param result
     * @return validation level from 0 to max integer. <br/>
     *         If method returns boolean it is appreciates as true = 1, false = 0.
     * @throws ParameterRelatedException
     */
    public int validate(final Object result) {
        try {
            Object r = method.invoke(invocationObject, result);
            if (r instanceof Boolean) {
                return ((Boolean) r) ? 1 : 0;
            }
            if (r instanceof Number) {
                return ((Number) r).intValue();
            }
        } catch (IllegalArgumentException e) {
            throwUnexpected(e);
        } catch (IllegalAccessException e) {
            throwUnexpected(e);
        } catch (InvocationTargetException e) {
            throwUnexpected(e);
        }
        return 0;
    }
    
    private UnexpectedInteractionException throwUnexpected(final Exception e) {
        throw new UnexpectedInteractionException("Error when invoking method: '" + method.getName() + "'", e);
    }
    
}
